package cn.cloud9.designpattern.dp03prototype;

import java.io.*;
import java.util.ArrayList;
import java.util.List;

/**
 * @author OnCloud9
 * @description
 * @project Java
 * @date 2022年05月22日 16:59
 */
public class Student implements
        Cloneable,
        DeepCloneable<Student> {

    private String name;
    private Integer id;
    private Integer age;
    private Boolean gender;
    private String status;
    private List<String> family;

    public Student() {
    }

    public Student(String name, Integer id, Integer age, Boolean gender, String status, List<String> family) {
        this.name = name;
        this.id = id;
        this.age = age;
        this.gender = gender;
        this.status = status;
        this.family = family;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", id=" + id +
                ", age=" + age +
                ", gender=" + gender +
                ", status='" + status + '\'' +
                ", family=" + family +
                "} " + super.toString();
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public Boolean getGender() {
        return gender;
    }

    public void setGender(Boolean gender) {
        this.gender = gender;
    }

    public String getStatus() {
        return status;
    }

    public void setStatus(String status) {
        this.status = status;
    }

    public List<String> getFamily() {
        return family;
    }

    public void setFamily(List<String> family) {
        this.family = family;
    }

    /**
     * 重新JDK提供的Clone方法，需要实现Cloneable接口，
     * @return
     */
    @Override
    public Student clone() {
        try {
            Student clone = (Student) super.clone();
            // TODO: copy mutable state here, so the clone can't change the internals of the original
            return clone;
        } catch (CloneNotSupportedException e) {
            throw new AssertionError();
        }
    }


    /**
     * 深拷贝方法，需要序列化接口支持，这里直接采用字节数组实现
     * 也可以使用JSON处理，原理是一样的，都需要序列化完成
     * @param <T>
     * @return
     * @throws IOException
     */
    @Override
    public <T> T deepClone() throws IOException {
        ByteArrayOutputStream byteArrayOutputStream = null;
        ObjectOutputStream objectOutputStream = null;

        ByteArrayInputStream byteArrayInputStream = null;
        ObjectInputStream objectInputStream = null;
        try {
            byteArrayOutputStream = new ByteArrayOutputStream();
            objectOutputStream = new ObjectOutputStream(byteArrayOutputStream);
            objectOutputStream.writeObject(this);

            byteArrayInputStream = new ByteArrayInputStream(byteArrayOutputStream.toByteArray());
            objectInputStream = new ObjectInputStream(byteArrayInputStream);
            final Object object = objectInputStream.readObject();

            return (T) object;
        } catch (Exception exception) {
            exception.printStackTrace();
        } finally {
            objectOutputStream.close();
            byteArrayOutputStream.close();

            objectInputStream.close();
            byteArrayInputStream.close();
        }
        return null;
    }

    public static void main(String[] args) throws IOException {
        final Student student = new Student(
                "阿伟",
                1001,
                22,
                true,
                "在读",
                new ArrayList<String>() {{
                    this.add("哥哥");
                    this.add("姐姐");
                }});
        // final Student clone = student.clone();
        final Student clone = student.deepClone();
        System.out.println(student);
        System.out.println(clone);
        // 可以发现克隆的结果 对引用类型不起作用，引用的资源是同一个
        System.out.println(student.getFamily() == clone.getFamily());

    }


}
